package cn.player.download;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;

import android.os.Handler;
import android.os.Message;
import cn.player.utils.AESUtil;
import cn.player.utils.Constant;
import cntv.player.core.util.LogUtil;

public class DownLoadHelper {
	
	public static final int MSG_DOWNLOAD_START = 100;
	public static final int MSG_DOWNLOAD_ING = 101;
	public static final int MSG_DOWNLOAD_CANCEL = 102;
	public static final int MSG_DOWNLOAD_SUCCESS = 103;
	public static final int MSG_DOWNLOAD_ERROR = 104;
	public static final int MSG_DOWNLOAD_PAUSE = 105;

	private static DownLoadHelper mDownLoadHelper;
	private static final int sNotifySize = 64 * 1024; // 每下载64KB通知进度条更新。
	private int mNotifyCurrent = 0; // 当前下载大小，当累积到64KB，清零
	private volatile boolean mIsCancelDownLoad; // 是否取消下载
	private volatile boolean mIsPauseDownLoad; // 是否暂停下载
	private boolean mIsDownLoadError; // 是否下载错误

	private DownLoadHelper() {
	}

	public static synchronized DownLoadHelper getInstance() {
		if (mDownLoadHelper == null) {
			mDownLoadHelper = new DownLoadHelper();
		}
		return mDownLoadHelper;
	}

	public void cancelDownLoad() {
		mIsCancelDownLoad = true;
	}
	
	public void pauseDownLoad() {
		mIsPauseDownLoad = true;
	}
	
	public void resumeDownLoad() {
		mIsPauseDownLoad = false;
	}
	
	
	public void decryptTsFile(List<String> sourceUrls, int startIndex, Handler handler, String filepath) {
		boolean isPaused = false;
		for (int i = startIndex; i < sourceUrls.size() && !isPaused; i++) {
			InputStream is = null;
			BufferedInputStream bis = null;
			FileOutputStream fos = null;
			File file = null;
			try {
				String sourceUrl = sourceUrls.get(i);
				is = new FileInputStream(sourceUrl);
				bis = new BufferedInputStream(is);
				
				file = new File(filepath);
				String fileName = null;
				if(sourceUrl.contains("?")){
					fileName = sourceUrl.substring(22, sourceUrl.length()); 
				}else{
					fileName = sourceUrl.substring(sourceUrl.lastIndexOf("/"), sourceUrl.length());
				}
				fileName = fileName.replace(".ts", Constant.SUFFIX_VIDEO);
				fos = new FileOutputStream(file + fileName);
				byte[] buffer = new byte[1024*4];
				int len = 0;
				boolean flag = true;
				while ((len = bis.read(buffer)) != -1) {
					if(flag && fileName.endsWith(Constant.SUFFIX_VIDEO)){
						flag = false; 
//						for (int j = 0; j < buffer.length; j++) {
//							buffer[j]=(byte) (buffer[j]^100);//进行和100异或 加密
//						}
						buffer = AESUtil.decrypt(buffer, AESUtil.PSD);
					}
					fos.write(buffer, 0, len); 
					if (mIsCancelDownLoad) {
						isPaused = true;
						break;
					}
					if (mIsPauseDownLoad) {
						isPaused = true;
						break;
					}
				}
				 if(!isPaused){
					 sendDownLoadIngMsg(handler, i + 1);
				 }
			} catch (Exception e) {
				mIsDownLoadError = true;
				LogUtil.e("zl", "DownloadManager error e = " + e.toString());
				e.printStackTrace();
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (bis != null) {
					try {
						bis.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (fos != null) {
					try { 
						fos.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (!mIsDownLoadError && !mIsCancelDownLoad && !mIsPauseDownLoad&& (i == sourceUrls.size() - 1)) {
					sendSuccessMessage(handler);
				} else if (mIsCancelDownLoad) {
					isPaused = true;
					sendCancelMessage(handler);
					deleteFailFile(file);
				} else if (mIsDownLoadError) {
					isPaused = true;
					sendErrorMessage(handler);
					deleteFailFile(file);
				} else if (mIsPauseDownLoad) {
					isPaused = true;
					sendPauseMessage(handler);
				}
				mIsDownLoadError = false;
				mIsCancelDownLoad = false;
				mNotifyCurrent = 0;
			}
		}
	}
	
	// java 合并两个byte数组
	public byte[]  copy(byte[] sour_byte,byte[] desti_byte) {
		byte[] new_byte = new byte[desti_byte.length + sour_byte.length];
		System.arraycopy(sour_byte, 0, new_byte, 0, sour_byte.length);
		System.arraycopy(desti_byte, 0, new_byte, sour_byte.length, desti_byte.length);
		
		return new_byte;
	}
	
	private void encryptFile(String sourceUrl,String destiUrl){ 
		File file = null;
		InputStream is = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		try {
			file = new File(sourceUrl);
			is = new FileInputStream(file);
			bis = new BufferedInputStream(is);
			
			fos = new FileOutputStream(destiUrl);
			byte[] buffer = new byte[1024];
			int len = 0;
			int length = 0;
			while ((len = bis.read(buffer)) != -1) {
				length = length + len;
				if (length <= Constant.KB_BYTE) {
					LogUtil.i("zl", "encryptFile() len = " + len + ",length = " + length);
					buffer = AESUtil.encrypt(buffer, AESUtil.PSD);
					LogUtil.i("zl", "buffer.length = " + buffer.length);
				}
				fos.write(buffer, 0, len);
			}
			file.delete();
		} catch (Exception e) {
			LogUtil.e("zl", "DownloadManager error e = " + e.toString());
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try { 
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void download(List<String> sourceUrls, int startIndex, Handler handler, String filepath) {
		
		boolean isPaused = false;
		for (int i = startIndex; i < sourceUrls.size() && !isPaused; i++) {
			InputStream is = null;
			BufferedInputStream bis = null;
			FileOutputStream fos = null;
			File file = null;
			try {
				String sourceUrl = sourceUrls.get(i);
				URL url = new URL(sourceUrl); 
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				conn.setConnectTimeout(5000);
				int contentLength = conn.getContentLength();
				LogUtil.i("zl", "download() contentLength = " + contentLength);
				sendStartMessage(handler, i);
				is = conn.getInputStream();
				bis = new BufferedInputStream(is);
				file = new File(filepath);
				String fileName = null;
				if(sourceUrl.contains("?")){
					fileName = sourceUrl.substring(22, sourceUrl.length()); 
				}else{
					fileName = sourceUrl.substring(sourceUrl.lastIndexOf("/"), sourceUrl.length());
				}
				fos = new FileOutputStream(file + fileName);
				
				int BUFFER_SIZE = 1024;
				byte[] buffer = new byte[BUFFER_SIZE];
				int len = 0;
				while ((len = bis.read(buffer)) != -1) {
//					LogUtil.i("zl", "download() len = " + len);
					fos.write(buffer, 0, len); 
					
					if (mIsCancelDownLoad) {
						isPaused = true;
						break;
					}
					if (mIsPauseDownLoad) {
						isPaused = true;
						break;
					}
				}
				
				String newFileName = fileName.replace(".ts", Constant.SUFFIX_VIDEO);
				encryptFile(file + fileName,file+newFileName);
				 if(!isPaused){
					 sendDownLoadIngMsg(handler, i + 1);
				 }
			} catch (Exception e) {
				mIsDownLoadError = true;
				LogUtil.e("zl", "DownloadManager error e = " + e.toString());
				e.printStackTrace();
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (bis != null) {
					try {
						bis.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (fos != null) {
					try { 
						fos.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (!mIsDownLoadError && !mIsCancelDownLoad && !mIsPauseDownLoad&& (i == sourceUrls.size() - 1)) {
					sendSuccessMessage(handler);
				} else if (mIsCancelDownLoad) {
					isPaused = true;
					sendCancelMessage(handler);
					deleteFailFile(file);
				} else if (mIsDownLoadError) {
					isPaused = true;
					sendErrorMessage(handler);
					deleteFailFile(file);
				} else if (mIsPauseDownLoad) {
					isPaused = true;
					sendPauseMessage(handler);
				}
				mIsDownLoadError = false;
				mIsCancelDownLoad = false;
				mNotifyCurrent = 0;
			}
		}
	}

	/**
	 * 从服务器下载apk
	 */
	public synchronized void download(String sourceUrl, Handler handler, String filepath) {
		InputStream is = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			URL url = new URL(sourceUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			sendStartMessage(handler, conn.getContentLength());
			is = conn.getInputStream();
			bis = new BufferedInputStream(is);
			file = new File(filepath);
			fos = new FileOutputStream(file + sourceUrl.substring(sourceUrl.lastIndexOf("/"), sourceUrl.length()));
			byte[] buffer = new byte[1024];
			int len = 0;
			int currentTotal = 0;
			while ((len = bis.read(buffer)) != -1) {
				fos.write(buffer, 0, len);
				currentTotal += len;
				mNotifyCurrent += len;
				if (mNotifyCurrent >= sNotifySize) {
					sendDownLoadIngMsg(handler, currentTotal);
					mNotifyCurrent = 0;
				}
				if (mIsCancelDownLoad) {
					break;
				}
			}
			sendDownLoadIngMsg(handler, currentTotal);
		} catch (Exception e) {
			mIsDownLoadError = true;
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (!mIsDownLoadError && !mIsCancelDownLoad) {
				sendSuccessMessage(handler);
			} else if (mIsCancelDownLoad) {
				sendCancelMessage(handler);
				deleteFailFile(file);
			} else if (mIsDownLoadError) {
				sendErrorMessage(handler);
				deleteFailFile(file);
			}
			mIsDownLoadError = false;
			mIsCancelDownLoad = false;
			mNotifyCurrent = 0;
		}
	}

	private void sendStartMessage(Handler handler, int fileMax) {
		Message startMsg = Message.obtain();
		startMsg.what = MSG_DOWNLOAD_START;
		startMsg.obj = fileMax;
		handler.sendMessage(startMsg);
	}

	private void sendDownLoadIngMsg(Handler handler, int currentTotal) {
		Message downLoadIngMsg = Message.obtain();
		downLoadIngMsg.what = MSG_DOWNLOAD_ING;
		downLoadIngMsg.obj = currentTotal;
		handler.sendMessage(downLoadIngMsg);
	}

	private void sendCancelMessage(Handler handler) {
		handler.sendEmptyMessage(MSG_DOWNLOAD_CANCEL);
	}

	private void sendSuccessMessage(Handler handler) {
		handler.sendEmptyMessage(MSG_DOWNLOAD_SUCCESS);
	}

	private void sendErrorMessage(Handler handler) {
		handler.sendEmptyMessage(MSG_DOWNLOAD_ERROR);
	}
	
	private void sendPauseMessage(Handler handler) {
		handler.sendEmptyMessage(MSG_DOWNLOAD_PAUSE);
	}

	private void deleteFailFile(File file) {
		if (file != null && file.exists()) {
			file.delete();
		}
	}

}